package ginx

import (
	"gitee.com/youkelike/zerror"
	"gitee.com/youkelike/zvalidation"
	"github.com/gin-gonic/gin"
)

// Validator 是具体验证函数签名
// type Validator[T any] func(context.Context, *T) error

// Binder 定义 gin 的 ShouldBindXxx 系列函数的签名
type Binder func(any) error

// 下面三个方法仅执行请求数据绑定和验证、还会调用实际的业务处理逻辑函数，
func HandleJSONRequest[T any](c *gin.Context, req *T, validators ...zvalidation.ValidateFunc[T]) error {
	return HandleRequest(c, c.ShouldBindJSON, req, validators...)
}
func HandleQueryRequest[T any](c *gin.Context, req *T, validators ...zvalidation.ValidateFunc[T]) error {
	return HandleRequest(c, c.ShouldBindQuery, req, validators...)
}
func HandleUriRequest[T any](c *gin.Context, req *T, validators ...zvalidation.ValidateFunc[T]) error {
	return HandleRequest(c, c.ShouldBindUri, req, validators...)
}

// HandleRequest 是通用的请求处理函数.
// - 它负责调用绑定函数绑定请求数据.
// - 如果目标类型实现了 Default 接口，会调用其 Default 方法设置默认值.
// - 最后执行传入的验证器对数据进行校验.
func HandleRequest[T any](c *gin.Context, binder Binder, req *T, validators ...zvalidation.ValidateFunc[T]) error {
	// 绑定请求数据
	if err := binder(req); err != nil {
		return zerror.ErrBind.WithMessage(err.Error())
	}

	// 如果数据结构实现了 Default 接口，则调用它的 Default 方法
	if defaulter, ok := any(req).(interface{ Default() }); ok {
		defaulter.Default()
	}

	// 执行所有验证函数
	for _, validate := range validators {
		if validate == nil { // 跳过 nil 的验证器
			continue
		}
		if err := validate(c.Request.Context(), req); err != nil {
			return err
		}
	}

	return nil
}
